package com.stylefeng.guns.rest.modular.App.service.impl;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.cache.CacheKit;
import com.stylefeng.guns.core.model.CommonKeyValue;
import com.stylefeng.guns.core.model.Pager;
import com.stylefeng.guns.rest.common.persistence.model.DriverInf;
import com.stylefeng.guns.rest.modular.App.dao.TaskInfMapper;
import com.stylefeng.guns.rest.modular.App.model.*;
import com.stylefeng.guns.rest.modular.App.service.*;
import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
import com.stylefeng.guns.rest.modular.auth.validator.IDriverInfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;


/**

 * 任务信息表 Service 实现
 * @author 张亚林
 * @Date 2018-11-12 17:05
 */
@Service
public class TaskInfServiceImpl extends ServiceImpl<TaskInfMapper,TaskInf> implements ITaskInfService {

    @Resource
    private TaskInfMapper taskInfMapper;
    @Autowired
    private IOrderInfService orderInfService;
    @Autowired
    private ITaskOrderService taskOrderService;
    @Autowired
    private ITaskReleaseService taskReleaseService;
    @Autowired
    private ITaskReleaseReasonService taskReleaseReasonService;
    @Autowired
    private IDriverInfService driverInfService;
    @Autowired
    private IDriverRefuseTaskService driverRefuseTaskService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;


    private static  final String TRANSFERCACHE="CONSTANT";

    @Transactional
    public int refuseTask(String tiId, String trrId, String token) throws Exception {


        //检测 TiId
        TaskInf taksInf=this.taskInfMapper.findTaskInfForUpdate(tiId);
        if(taksInf==null){
            throw  new RuntimeException("任务包不存在！");
        }
        DriverInf driverInf=CacheKit.get(TRANSFERCACHE,jwtTokenUtil.getUsernameFromToken(token));
        if(!taksInf.getDiId().equals(driverInf.getDiId())){
            throw  new RuntimeException("任务包已经指派他人，不能操作！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("3") ){
            throw  new RuntimeException("任务包未指派或已经完成，不能操作！");
        }

        //检测 trrId
        TaskReleaseReason taskReleaseReason=taskReleaseReasonService.findTaskReleaseReasonById(trrId,token);
        if(taskReleaseReason==null){
            throw  new RuntimeException("拒绝原因不存在！");
        }

        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
        for(TaskOrder en:listTaskOrder){
            OrderInf orderInf= orderInfService.findOrderInfForUpdate(en.getOiId());
            if(orderInf.getCiState().equals("1") || orderInf.getCiState().equals("3") ){
                throw  new RuntimeException("乘客已经上车或者下车，不能操作！");
            }
        }

        //减少驾驶员任务数
        DriverInf updateDriverInf=new DriverInf();
        updateDriverInf.setDiId(driverInf.getDiId());
        updateDriverInf.setDiTaskNum(-1);
        driverInfService.updateDriverInfTaskNum(updateDriverInf,token);
        //更新曾经派单的过程
        TaskRelease taskRelease=new TaskRelease();
        taskRelease.setTiId(tiId);
        taskRelease.setDiId(driverInf.getDiId());
        taskRelease.setTrrId(trrId);
        taskReleaseService.updateTaskReleaseRefuse(taskRelease,token);
        //更新任务包为未指派
        Date currentTime=DateTime.now();
        taksInf.setUpdateTime(currentTime);
        taksInf.setUpdateUser(driverInf.getDiId());
        this.taskInfMapper.updateTaskRefuse(taksInf);

        //添加拒绝接单提醒
        DriverRefuseTask driverRefuseTask=new DriverRefuseTask();
        driverRefuseTask.setDrtReadFlg("0");
        driverRefuseTask.setDrtReason(taskReleaseReason.getTrrReason());
        driverRefuseTask.setDiId(driverInf.getDiId());
        driverRefuseTask.setTiId(tiId);
        driverRefuseTaskService.insertDriverRefuseTask(driverRefuseTask,token);
        return 0;
    }

    /**
     * 查询任务信息表列表
     * @param taskInf 任务信息表对象
     * @return
     */
    public List<TaskInf> selectListTaskInf(TaskInf taskInf,String token)throws Exception{
        return  this.taskInfMapper.selectListTaskInf(taskInf);
    }

    @Override
    public List<TaskInf> selectFirstListTaskInf(TaskInf taskInf, String token) throws Exception {
        if(taskInf==null){
            taskInf=new TaskInf();
        }

        DriverInf driverInf=CacheKit.get(TRANSFERCACHE,jwtTokenUtil.getUsernameFromToken(token));
        taskInf.setDiId(driverInf.getDiId());
        if(taskInf.getTiState()==null){
            taskInf.setTiState("1");
        }

        TaskInf selTaskInf=new TaskInf();
        selTaskInf.setDiId(driverInf.getDiId());
        selTaskInf.setIsExcute("1");
        List<TaskInf> listTaskInf=this.taskInfMapper.selectListTaskInf(selTaskInf);
        if(listTaskInf!=null && listTaskInf.size()>0){
            List<TaskInf> listUnTaskInf=this.taskInfMapper.selectFirstListTaskInf(taskInf);
            listTaskInf.addAll(listUnTaskInf);
        }else{
            listTaskInf=this.taskInfMapper.selectFirstListTaskInf(taskInf);
        }
        return listTaskInf;
    }
    /**
	 * 分页查询任务信息表列表
     * @param pager 分页对象
     * @return
     */
    public  Map pageListTaskInf(Pager pager,String token) throws Exception{
        DriverInf driverInf=CacheKit.get(TRANSFERCACHE,jwtTokenUtil.getUsernameFromToken(token));
        Page page=new Page(pager.getPageNumber(),pager.getPageSize());
        TaskInf taskInf=(TaskInf)pager.getObj();
        taskInf.setDiId(driverInf.getDiId());
        /*if(taskInf.getTiState()==null){
            taskInf.setTiState("1");
        }*/
        page.setRecords(taskInfMapper.selectListTaskInf(page,taskInf));
        List<TaskInf> list = page.getRecords();

        if(pager.getPageNumber()==1){
            TaskInf selTaskInf=new TaskInf();
            selTaskInf.setDiId(driverInf.getDiId());
            selTaskInf.setIsExcute("1");
            List<TaskInf> listTaskInf=this.taskInfMapper.selectListTaskInf(selTaskInf);
            if(listTaskInf!=null && listTaskInf.size()>0){
                listTaskInf.addAll(list);
            }
        }
        Map mapDate = new HashMap();
        mapDate.put("rows", list);
        mapDate.put("total", page.getTotal());
        mapDate.put("page", page.getCurrent());
        mapDate.put("pageCount", page.getPages());
        return mapDate;
    }
    /**
     * 同一个事务 互斥锁查询
     * @param taskInf 任务信息表对象
     * @return
     */
    public  List<TaskInf> selectListTaskInfForUpdate(TaskInf taskInf)throws Exception{
        return  this.taskInfMapper.selectListTaskInfForUpdate(taskInf);
    }
    /**
     * 通过主键id查询的任务信息表列表
     * @param id 主键id
     * @return
     */
    public  TaskInf findTaskInfById(String id,String token)throws Exception{
        return  this.taskInfMapper.findTaskInfById(id);
    }

    /**
     * 互斥锁查询任务
     * @param id 主键id
     * @return
     */
    public TaskInf findTaskInfForUpdate(String id) throws Exception {
        return this.taskInfMapper.findTaskInfForUpdate(id);
    }

    /**
     * 查询任务信息表返回key-Value属性
     * @param taskInf 系统操作对象
     * @return
     */
    public List<CommonKeyValue> optionsTaskInf(TaskInf taskInf,String token) throws Exception {
        List<TaskInf> listTaskInf=this.taskInfMapper.selectListTaskInf(taskInf);
        List<CommonKeyValue> listOptions=new ArrayList<CommonKeyValue>();
        for(TaskInf item:listTaskInf){
            CommonKeyValue opts=new CommonKeyValue();
            opts.setId(""+item.getTiId());
            opts.setValue(item.getTiCode());
            listOptions.add(opts);
        }
        return listOptions;
    }

    /**
     * 更新任务单信息数据
     * @param taskInf 任务单信息对象
     * @return
     */
    @Transactional
    public int updateTaskInf(TaskInf taskInf, String token) throws Exception {
       this.taskInfMapper.updateTaskInf(taskInf);
       return 0;

    }

    /**
     * 开始执行任务，将任务中乘客修改后成已上车
     * @param tiId 任务单信息对象
     * @param onAddr 地址
     * @param onPos 执行经纬度
     * @param token
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public int updateStartTaskInf(String tiId, String onAddr, String onPos, String token) throws Exception {
        if(tiId==null || tiId.trim().length()<10 ){
            throw new RuntimeException("参数不全！");
        }

        if(onAddr==null || onAddr.trim().length()<3 || onPos==null || onPos.trim().length()<10){
            throw  new RuntimeException("执行任务经纬度和地址都不能为空！");
        }
        //检查任务包状态
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null ){
            throw  new RuntimeException("任务包不存在！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("2")){
            throw  new RuntimeException("任务包未指派或者已经完成！");
        }
        DriverInf driverInf=CacheKit.get(TRANSFERCACHE,jwtTokenUtil.getUsernameFromToken(token));
        String diId=driverInf.getDiId();
        if(!taksInf.getDiId().equals(diId)){
            throw  new RuntimeException("任务包已经指派他人！");
        }

        Date curDate=new Date();
        //查询所有任务单中的乘客修改成上车 并且记录完成经纬度和时间
        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
        for(TaskOrder en:listTaskOrder){
            OrderInf orderInf= this.orderInfService.findOrderInfForUpdate(en.getOiId());
            //将未上车的乘客状态变成已上车
            if(orderInf.getCiState().equals("0")){
                orderInf.setCiGetOnTime(curDate);
                orderInf.setCiGetOnPos(onPos);
                orderInf.setCiGetOnAddr(onAddr);
                this.orderInfService.updateOrderInfUp(orderInf,token);
            }
        }
        //设置任务变成已经执行
        TaskInf updateTaksInf=new TaskInf();
        updateTaksInf.setTiId(tiId);
        updateTaksInf.setUpdateTime(curDate);
        updateTaksInf.setTiStartTime(curDate);
        updateTaksInf.setTiStartPoint(onPos);
        updateTaksInf.setCtStartAddress(onAddr);
        updateTaksInf.setDiSelected("0");
        this.updateTaskInf(updateTaksInf,token);
        return 0;
    }

    /**
     * 结束任务，将任务中乘客修改后成已下车，减小驾驶员的任务数
     * @param tiId 任务单信息对象
     * @param offAddr 地址
     * @param offPos 结束经纬度
     * @param token
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateEndTaskInf(String tiId, String offAddr, String offPos, String token) throws Exception {
        if(tiId==null || tiId.trim().length()<10){
            throw new RuntimeException("参数不全！");
        }
        if(offAddr==null || offAddr.trim().length()<3 || offPos==null || offPos.trim().length()<10){
            throw  new RuntimeException("结束任务经纬度和地址都不能为空！");
        }
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null ){
            throw  new RuntimeException("任务包不存在！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("2")){
            throw  new RuntimeException("任务包未指派或者已经完成！");
        }
        DriverInf driverInf=CacheKit.get(TRANSFERCACHE,jwtTokenUtil.getUsernameFromToken(token));
        String diId=driverInf.getDiId();
        if(!taksInf.getDiId().equals(diId)){
            throw  new RuntimeException("任务包已经指派他人！");
        }
        Date curDate=new Date();
        //查询所有任务单中的乘客修改成已经下车 并且记录完成经纬度和时间
        TaskOrder taskOrder=new TaskOrder();
        taskOrder.setTiId(tiId);
        List<TaskOrder> listTaskOrder=taskOrderService.selectListTaskOrder(taskOrder,token);
        for(TaskOrder en:listTaskOrder){
            OrderInf orderInf= this.orderInfService.findOrderInfForUpdate(en.getOiId());
            //将未上车的乘客状态变成已上车
            if(orderInf.getCiState().equals("1")){
                orderInf.setCiGetOffTime(curDate);
                orderInf.setCiGetOffPos(offPos);
                orderInf.setCiGetOffAddr(offAddr);
                this.orderInfService.updateOrderInfDown(orderInf,token);
            }
        }

        TaskInf updateTaksInf=new TaskInf();
        updateTaksInf.setTiId(tiId);
        updateTaksInf.setUpdateTime(curDate);
        updateTaksInf.setTiEndTime(curDate);
        updateTaksInf.setTiEndPoint(offPos);
        updateTaksInf.setCtEndAddress(offAddr);
        updateTaksInf.setTiState("2");
        updateTaksInf.setDiSelected("0");
        this.updateTaskInf(updateTaksInf,token);
        //减少原驾驶员任务数
        DriverInf updateDriverInf=new DriverInf();
        updateDriverInf.setDiId(driverInf.getDiId());
        updateDriverInf.setDiTaskNum(-1);
        driverInfService.updateDriverInfTaskNum(updateDriverInf,token);
        return 0;
    }

    @Override
    public int updateSelectTask(String tiId, String token) throws Exception {
        TaskInf taksInf=this.findTaskInfForUpdate(tiId);
        if(taksInf==null ){
            throw  new RuntimeException("任务包不存在！");
        }
        DriverInf driverInf=CacheKit.get(TRANSFERCACHE,jwtTokenUtil.getUsernameFromToken(token));
        String diId=driverInf.getDiId();
        if(!taksInf.getDiId().equals(diId)){
            throw  new RuntimeException("任务包已经指派他人！");
        }
        if(taksInf.getTiState().equals("0") || taksInf.getTiState().equals("2")){
            throw  new RuntimeException("任务包未指派或者已经完成！");
        }
        if(taksInf.getTiStartTime()!=null || taksInf.getTiEndTime()!=null){
            throw  new RuntimeException("任务包已经执行！");
        }

        taksInf=new TaskInf();
        taksInf.setDiId(diId);
        taksInf.setTiState("1");
        List<TaskInf> listTaskInf=this.selectListTaskInfForUpdate(taksInf);
        for(TaskInf tmpTaskInf:listTaskInf){
            if(tmpTaskInf.getTiStartTime()!=null || tmpTaskInf.getTiEndTime()!=null){
                throw  new RuntimeException("已经有执行！");
            }
        }

        taksInf=new TaskInf();
        taksInf.setDiId(diId);
        this.taskInfMapper.updateTaskInfCancelSelect(taksInf);

        taksInf=new TaskInf();
        taksInf.setTiId(tiId);
        taksInf.setDiSelected("1");
        this.updateTaskInf(taksInf,token);
        return 0;
    }
}
